﻿using System;
using System.Net;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;

namespace Game.Lib
{
    public class UDPServer
    {
        public const int GATEWAY = 4096;
        public delegate void DataReceivedHandler(DataReceivedEventArgs e);
        public event DataReceivedHandler OnDataReceived;
        public IPEndPoint IP { get; set; }
        private Socket UDPSocket;
        private bool listening;
        private Thread listenThread;

        public UDPServer(IPEndPoint endpoint)
        {
            IP = endpoint;
        }
        public void Send(EndPoint remote, Packet packet)
        {
            foreach (MicroPacket mp in packet.ToMicroPackets())
            {
                UDPSocket.SendTo(mp.ToBytes(), remote);
            }
        }

        public void Send(EndPoint remote, byte[] buffer)
        {
            UDPSocket.SendTo(buffer, remote);
        }
        public void Stop()
        {
            listening = false;
            listenThread.Abort();
        }

        public void Start()
        {
            UDPSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            UDPSocket.Bind(IP);
            listening = true;
            listenThread = new Thread(new ThreadStart(Listen));
            listenThread.Start();
        }

        private void Listen()
        {
            IPEndPoint sender = new IPEndPoint(IPAddress.Any, IP.Port);
            EndPoint remote = (EndPoint)sender;
            while (listening)
            {
                byte[] buffer = new byte[MicroPacket.MAXIMUM_SIZE + MicroPacket.HEADER_SIZE];
                int recv = UDPSocket.ReceiveFrom(buffer, ref remote);
                Array.Resize(ref buffer, recv);
                if (OnDataReceived != null && remote != null)
                {
                    OnDataReceived(new DataReceivedEventArgs(remote, buffer));
                }
            }
        }
    }

    public class DataReceivedEventArgs : EventArgs
    {
        public EndPoint IP { get; set; }
        public byte[] Buffer { get; set; }

        public DataReceivedEventArgs(EndPoint ip, byte[] buffer)
        {
            IP = ip;
            Buffer = buffer;
        }
    }
}